package net.soevar.database.hibernate;


import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.metadata.ClassMetadata;
import org.zkoss.zk.ui.sys.ExecutionsCtrl;

public class HibernateUtil extends org.zkoss.zkplus.hibernate.HibernateUtil {

	@SuppressWarnings("rawtypes")
	public static synchronized ClassMetadata getClassMetadata(Class aClass) {
		return getSessionFactory().getClassMetadata(aClass);
	}

	/**
	 * Gets Hibernate Session for current thread. When finished, users must
	 * return session using {@link #closeSession() closeSession()} method.
	 * 
	 * @return Hibernate Session for current thread.
	 * @throws HibernateException
	 *             if there is an error opening a new session.
	 */
	public static synchronized Session currentSession() {
		try {
			ExecutionsCtrl.getCurrentCtrl().getCurrentPage().getFirstRoot();
			return org.zkoss.zkplus.hibernate.HibernateUtil.currentSession();
		} catch (Exception e) {
			// e.printStackTrace();
			return currentNativeSession();
		}

	}

	@SuppressWarnings({ "unchecked" })
	public static synchronized Session currentNativeSession() {
		// configure();

		// Class myClass = null;
		// Integer line = 0;
		// try {
		// throw new Exception("Who called me?");
		// } catch (Exception e) {
		// try {
		// StackTraceElement[] elements = e.getStackTrace();
		// for (StackTraceElement element : elements) {
		// if (element.getClassName().startsWith("ais.action.master")) {
		// myClass = Class.forName(element.getClassName());
		// line = element.getLineNumber();
		// break;
		// }
		// }
		// } catch (Exception e1) {
		// e1.printStackTrace();
		// }
		// }
		// System.out.println("== currentNativeSession ===, myClass = "
		// + (myClass == null ? "" : myClass.getName()) + ", line = "
		// + line);

		Session s = getSessionFactory().openSession();
		// Open a new Session, if this Thread has none yet
		// if (s == null) {
		// s = getSessionFactory().openSession();
		MAP.set(s);
		// }
		return s;
	}

	/** ThreadLocal Session Map */
	@SuppressWarnings("rawtypes")
	private static final ThreadLocal MAP = new ThreadLocal();

	// private static final Logger LOG = Logger.getLogger(HibernateUtil.class);

	// private static SessionFactory SESSION_FACTORY;

	/** Make default construct private */
	private HibernateUtil() {
	}

	// private static boolean configured = false;

	/** Loads Hibernate config. */
	// private static synchronized void configure() {
	// try {
	// if (configured) {
	// return;
	// }
	// LOG.debug("HibernateUtil.static - loading config");
	// SESSION_FACTORY = new AnnotationConfiguration().configure()
	// .buildSessionFactory();
	// LOG.debug("HibernateUtil.static - end");
	// configured = true;
	// } catch (HibernateException ex) {
	// throw new RuntimeException("Exception building SessionFactory: "
	// + ex.getMessage(), ex);
	// }
	// }

	/**
	 * Closes the Hibernate Session. Users must call this method after calling
	 * {@link #currentSession() currentSession()}.
	 * 
	 * @throws HibernateException
	 *             if session has problem closing.
	 */
	@SuppressWarnings("unchecked")
	public static synchronized void closeSessionAfter()
			throws HibernateException {
		Thread thread = new Thread(new Runnable() {

			@Override
			public void run() {
				try {
					Thread.sleep(1500);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				Session s = (Session) MAP.get();
				MAP.set(null);
				if (s != null) {
					s.disconnect();
					s.close();
				}
			}
		});
		thread.start();
	}

	public static synchronized void rollbackTransaction() {
		try {
			// Transaction tx = threadTransaction.get();
			// threadTransaction.set(null);
			Session s = (Session) MAP.get();
			if (s != null) {
				Transaction tx = s.getTransaction();
				System.out
						.println("====================== ROLLING BACK SESSION ============================== wasCommitted = "
								+ tx.wasCommitted()
								+ ", wasRolledBack = "
								+ tx.wasRolledBack());
				try {
					if (tx != null && !tx.wasCommitted() && !tx.wasRolledBack()) {
						tx.rollback();
					}
				} finally {
					closeSession();
				}
			}
		} catch (Exception e) {
			// e.printStackTrace();
		}

	}

	@SuppressWarnings("unchecked")
	public static synchronized void closeSession() throws HibernateException {
		Session s = (Session) MAP.get();
		MAP.set(null);
		if (s != null) {
			try {
				s.disconnect();
				s.close();
			} catch (Exception e) {
				// TODO: handle exception
			}
		}
	}

}
